package volkov.ja.util;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/*
 * Class that extracts database fixtures from the .fixtures.xml files
 */
public class FixtureLoader {

	private static final String FIX_SUFFIX = ".fixtures.xml";

	public TreeMap<String, String> getFixtures(String name) {
		TreeMap<String, String> queries = new TreeMap<String, String>();
		if (name == null || name.isEmpty()) {
			name = "default";
		}
		ArrayList<String> files = getFixturesFiles();
		for (String file : files) {
			try {
				DocumentBuilderFactory factory = DocumentBuilderFactory
						.newInstance();
				factory.setCoalescing(true);
				DocumentBuilder builder = factory.newDocumentBuilder();
				Document document = builder.parse(ClassLoader
						.getSystemResourceAsStream(file));
				XPathFactory xfactory = XPathFactory.newInstance();
				XPath xpath = xfactory.newXPath();
				try {
					NodeList nl = (NodeList) xpath.evaluate(
							"//fixtures/fixture[@name='" + name
									+ "']/queries/query", document,
							XPathConstants.NODESET);
					for (int i = 0; i < nl.getLength(); i++) {
						Node item = nl.item(i);
						Node content = (Node) xpath.evaluate("text()", item,
								XPathConstants.NODE);
						if (content != null) {
							queries.put(item.getAttributes()
									.getNamedItem("name").getNodeValue(), content.getNodeValue());
						}
					}
				} catch (XPathExpressionException e) {
					e.printStackTrace();
				}
			} catch (ParserConfigurationException e) {
				e.printStackTrace();
			} catch (SAXException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return queries;
	}

	private ArrayList<String> getFixturesFiles() {
		ArrayList<String> fixtureFiles = new ArrayList<String>();
		String path = getDataPath();
		File[] listOfFiles = new File(path).listFiles();
		for (int i = 0; i < listOfFiles.length; i++) {
			if (listOfFiles[i].isFile()) {
				String fname = listOfFiles[i].getName();
				if (fname.toLowerCase().endsWith(FIX_SUFFIX)) {
					fixtureFiles.add(fname);
				}
			}
		}
		return fixtureFiles;
	}

	// get absolute path of the class/jar directory
	private String getDataPath() {
		String out = "";
		try {
			String classPath = FixtureLoader.class.getProtectionDomain()
					.getCodeSource().getLocation().toURI().toString();
			classPath = classPath.replace("%20", " ");
			Matcher m = Pattern.compile("file:(.*?)(/[^/]+\\.jar.*)?$")
					.matcher(classPath);
			if (m.find()) {
				out = new File(m.group(1)).getAbsolutePath() + "/";
			}
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		return out;
	}

}